//
// Created by huangyang on 18-3-15.
//

#include "irrContex.h"
#include "irrlicht.h"
#include "item.h"

using namespace irr;

irrContex::irrContex(int width, int height,bool full) {
    device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(width, height),32,full);
    s_w = width;
    s_h = height;
    if (device == 0) return;
    driver = device->getVideoDriver();
    smgr = device->getSceneManager();
    env = device->getGUIEnvironment();
    mainCam = smgr->addCameraSceneNode(0,core::vector3df(0,0,0),core::vector3df(0,0,-100));
    mainCam->bindTargetAndRotation(true);
    cams[0] = smgr->addCameraSceneNode(mainCam, core::vector3df(0.05, 0, 0), core::vector3df(0, 0, -100));
    cams[1] = smgr->addCameraSceneNode(mainCam, core::vector3df(-0.05, 0, 0), core::vector3df(0, 0, -100));
    cams[0]->bindTargetAndRotation(true);
    cams[1]->bindTargetAndRotation(true);
    itemList.clear();
    new_id = 0;
    tmp = L"NEF";
    device->setWindowCaption(tmp.c_str());
    env->getSkin()->setFont(env->getFont("font/fontlucida.png"));
}

irrContex::~irrContex() {
    device->drop();
}

int irrContex::addItem(item_type_t item_type, const char *initData, int x1, int y1, int x2, int y2) {
    if (item_type == MOD) {
        scene::IAnimatedMesh *mesh;
        mesh = smgr->getMesh(initData);
        if (mesh) {
            scene::ISceneNode *node = smgr->addOctreeSceneNode(mesh->getMesh(0), 0);
            item *new_item = new item();
            new_item->existence = true;
            new_item->visitable = true;
            new_item->noticed = false;
            new_item->clicked = false;
            new_item->node = node;
            new_item->node->setMaterialFlag(video::EMF_LIGHTING, false);
            new_item->type = MOD;
            new_id++;
            new_item->id = new_id;
            new_item->node->setID(new_id);
            itemList.push_back(new_item);
            return new_id;
        }
    }
    if (item_type == TEX) {
        item *new_item = new item();
        new_item->text = env->addStaticText(
                L"",
                core::rect<s32>(x1, y1, x2, y2));
        new_item->existence = true;
        new_item->visitable = true;
        new_item->noticed = false;
        new_item->clicked = false;
        new_item->type = TEX;
        new_id++;
        new_item->id = new_id;
        itemList.push_back(new_item);
        return new_id;
    }
    if (item_type == IMG) {
        item *new_item = new item();
        new_item->image = env->addImage(driver->getTexture(initData), core::position2di(x1, y1));
        new_item->existence = true;
        new_item->visitable = true;
        new_item->noticed = false;
        new_item->clicked = false;
        new_item->type = IMG;
        new_id++;
        new_item->id = new_id;
        itemList.push_back(new_item);
        return new_id;
    }
    return -1;
}

int irrContex::addItem(int id,item_type_t item_type, const char *initData, int x1, int y1, int x2, int y2) {
    new_id = id - 1;
    if (item_type == MOD) {
        scene::IAnimatedMesh *mesh;
        mesh = smgr->getMesh(initData);
        if (mesh) {
            scene::ISceneNode *node = smgr->addOctreeSceneNode(mesh->getMesh(0), 0);
            item *new_item = new item();
            new_item->existence = true;
            new_item->visitable = true;
            new_item->noticed = false;
            new_item->clicked = false;
            new_item->node = node;
            new_item->node->setMaterialFlag(video::EMF_LIGHTING, false);
            new_item->type = MOD;
            new_id++;
            new_item->id = new_id;
            new_item->node->setID(new_id);
            itemList.push_back(new_item);
            return new_id;
        }
    }
    if (item_type == TEX) {
        item *new_item = new item();
        new_item->text = env->addStaticText(
                L"",
                core::rect<s32>(x1, y1, x2, y2));
        new_item->existence = true;
        new_item->visitable = true;
        new_item->noticed = false;
        new_item->clicked = false;
        new_item->type = TEX;
        new_id++;
        new_item->id = new_id;
        itemList.push_back(new_item);
        return new_id;
    }
    if (item_type == IMG) {
        item *new_item = new item();
        new_item->image = env->addImage(driver->getTexture(initData), core::position2di(x1, y1));
        new_item->existence = true;
        new_item->visitable = true;
        new_item->noticed = false;
        new_item->clicked = false;
        new_item->type = IMG;
        new_id++;
        new_item->id = new_id;
        itemList.push_back(new_item);
        return new_id;
    }
    return -1;
}

int irrContex::delItem(int id) {
    item *i;
    for (auto itor = itemList.begin(); itor != itemList.end(); itor++) {
        i = *itor.base();
        if (i->id == id) {
            if (i->type == MOD) {
                i->node->remove();
            }
            if (i->type == IMG) {
                i->image->remove();
            }
            if (i->type == TEX) {
                i->text->remove();
            }
            delete i;
            itemList.erase(itor);
            return 0;
        }
    }
    return -1;
}

item *irrContex::getItem(int id) {
    item *i;
    for (auto itor = itemList.begin(); itor != itemList.end(); itor++) {
        i = *itor.base();
        if (i->id == id) {
            return i;
        }
    }
    return nullptr;
}

int irrContex::refleshClick() {
    scene::ISceneNode *selectedSceneNode = smgr->getSceneCollisionManager()->getSceneNodeFromCameraBB(cams[0]);
    item *i;

    for (auto itor = itemList.begin(); itor != itemList.end(); itor++) {
        i = *itor.base();
        if (selectedSceneNode != nullptr && i->id == selectedSceneNode->getID()) {
            i->clicked = true;
        } else {
            i->clicked = false;
        }
    }

    for (auto itor = itemList.begin(); itor != itemList.end(); itor++) {
        i = *itor.base();
        if (i->clicked == true) {
            if (i->noticed == false) {
                i->noticed = true;
                return i->id;
            }
        } else {
            if (i->noticed == true) {
                i->noticed = false;
                return (-1) * i->id;
            }
        }
    }
    return 0;
}

int irrContex::setItemPos(int id, double x, double y, double z) {
    item *i = getItem(id);
    if (i != nullptr) {
        if (i->type == MOD) {
            i->node->setPosition(core::vector3df(x, y, z));
            i->posture[0] = x;
            i->posture[1] = y;
            i->posture[2] = z;
            return 0;
        }
        if (i->type == TEX) {
            i->text->setRelativePosition(core::position2di(x, y));
            i->posture[0] = x;
            i->posture[1] = y;
            return 0;
        }
        if (i->type == IMG) {
            i->image->setRelativePosition(core::position2di(x, y));
            i->posture[0] = x;
            i->posture[1] = y;
            return 0;
        }
        return -1;
    } else return -1;
}

int irrContex::setItemRot(int id, double x, double y, double z) {
    item *i = getItem(id);
    if (i != nullptr) {
        if (i->type == MOD) {
            i->node->setRotation(core::vector3df(x, y, z));
            i->posture[3] = x;
            i->posture[4] = y;
            i->posture[5] = z;
            return 0;
        }
        if (i->type == TEX) {
            return 0;
        }
        if (i->type == IMG) {
            return 0;
        }
        return -1;
    } else return -1;
}

int irrContex::setItemScale(int id, double x, double y, double z) {
    item *i = getItem(id);
    if (i != nullptr) {
        if (!(i->type == MOD)) {
            if (i->type == TEX) {
                return 0;
            }
            if (i->type == IMG) {
                return 0;
            }
            return -1;
        } else {
            i->node->setScale(core::vector3df(x, y, z));
            i->posture[6] = x;
            i->posture[7] = y;
            i->posture[8] = z;
            return 0;
        }
    } else return -1;
}

int irrContex::setItemVisitable(int id, bool visitable) {
    item *i = getItem(id);
    if (i != nullptr) {
        if (i->type == MOD) {
            i->node->setVisible(visitable);
            i->visitable = visitable;
            return 0;
        }
        if (i->type == TEX) {
            i->text->setVisible(visitable);
            i->visitable = visitable;
            return 0;
        }
        if (i->type == IMG) {
            i->image->setVisible(visitable);
            i->visitable = visitable;
            return 0;
        }
        return -1;
    } else return -1;
}

int irrContex::drawScene() {
    if (device->run()) {
        //Set the viewpoint to the whole screen and begin scene
        driver->setViewPort(core::rect<s32>(0, 0, s_w, s_h));
        driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255, 0, 0, 0));
        //If SplitScreen is used
        bool SplitScreen = true;
        if (SplitScreen) {
            smgr->setActiveCamera(cams[0]);
            driver->setViewPort(core::rect<s32>(0, 0, s_w / 2, s_h));
            //Draw scene
            smgr->drawAll();
            env->drawAll();
            //Activate camera2
            //smgr->setActiveCamera(cams[1]);
            smgr->setActiveCamera(cams[0]);
            //Set viewpoint to the second quarter (right top)
            driver->setViewPort(core::rect<s32>(s_w / 2, 0, s_w, s_h));
            //Draw scene
            smgr->drawAll();
            env->drawAll();
        }
        driver->endScene();
        return 0;
    } else {
        return -1;
    }
    return -1;
}

int irrContex::setItemText(int id, const wchar_t *tex) {
    item *i = getItem(id);
    if (i != nullptr) {
        if (i->type == TEX) {
            i->text->setText(tex);
            return 0;
        }
        return -1;
    } else return -1;
}

int irrContex::setCamPos(double x, double y, double z) {
    //mainCam->setPosition(core::vector3df(x, y, z));
    cams[0]->setPosition(core::vector3df(x, y, z));
    return 0;
}

int irrContex::setCamRot(double x, double y, double z) {
    //mainCam->setRotation(core::vector3df(x, y, z));
    cams[0]->setRotation(core::vector3df(x, y, z));
    return 0;
}

int irrContex::setCamTarget(double x, double y, double z) {
    //mainCam->setTarget(core::vector3df(x, y, z));
    cams[0]->setTarget(core::vector3df(x, y, z));
    return 0;
}